package com.qfedu.job;

import com.alibaba.druid.pool.DruidDataSource;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
import org.apache.mahout.cf.taste.impl.model.jdbc.MySQLJDBCDataModel;
import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood;
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;
import org.apache.mahout.cf.taste.similarity.UserSimilarity;
import org.apache.mahout.common.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;
import org.apache.mahout.cf.taste.impl.similarity.EuclideanDistanceSimilarity;
/**
 * 作者：刘随阳
 * 时间: 2021/8/12 10:10
 * 描述：神光照耀,太白成瑞。六丙来迎,百福悠归
 */
@Component
public class UserCFJob {

    final  int NEIGHBORHOOD_NUM = 10;   //用户邻居数量
    final  int RECOMMENDER_NUM = 5;    //推荐结果个数
    static DruidDataSource dataSource = new DruidDataSource();

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Scheduled(fixedDelay=5000)
    public void UserCF() throws TasteException, JsonProcessingException {
        // write your code here
        //随机种子
        RandomUtils.useTestSeed();

        //String file = "datafile/data.csv";   //数据集，其中第一列表示用户id；第二列表示商品id；第三列表示评分，评分是5分制
        //DataModel model = new FileDataModel(new File(file));  //基于文件的model，通过文件形式来读入,且此类型所需要读入的数据的格式要求很低，只需要满足每一行是用户id，物品id，用户偏好，且之间用tab或者是逗号隔开即可

        dataSource.setUsername("root");
        dataSource.setPassword("admin123");
        //dataSource.setDatabaseName("user_hobby");
        dataSource.setUrl("jdbc:mysql://118.31.245.151:3306/me?useUnicode=true&characterEncoding=utf-8&useSSL=false");
        //基于用户的协同过滤算法，基于物品的协同过滤算法
        DataModel model = new MySQLJDBCDataModel(dataSource, "user_hobby", "user_id", "item_id", "score", "CREATETIME");
        UserSimilarity similarity = new EuclideanDistanceSimilarity(model);  //计算欧式距离，欧式距离来定义相似性，用s=1/(1+d)来表示，范围在[0,1]之间，值越大，表明d越小，距离越近，则表示相似性越大
        NearestNUserNeighborhood neighbor = new NearestNUserNeighborhood(NEIGHBORHOOD_NUM, similarity, model);
        //指定用户邻居数量

        //构建基于用户的推荐系统
        Recommender r = new GenericUserBasedRecommender(model, neighbor, similarity);

//        List<RecommendedItem> recommend = r.recommend(userid.longValue(), RECOMMENDER_NUM);
//        System.out.printf("uid:%s",userid);
//        for(RecommendedItem ritem : recommend)
//        {
//            System.out.printf("(%s,%f)",ritem.getItemID(),ritem.getValue());
//        }
        System.out.println();
        //得到所有用户的id集合
        LongPrimitiveIterator iter = model.getUserIDs();

        while(iter.hasNext()) {
            Long uid = iter.nextLong();
            List<RecommendedItem> list = r.recommend(uid,RECOMMENDER_NUM);  //获取推荐结果
            ObjectMapper om = new ObjectMapper();
            System.out.printf("user:uid:%s",uid);
            //遍历推荐结果
            ArrayList<Integer> items = new ArrayList<>();
            for(RecommendedItem ritem : list) {
                System.out.printf("(%s,%f)",ritem.getItemID(),ritem.getValue());
                items.add((int) ritem.getItemID());
            }
            String s = om.writeValueAsString(items);
            stringRedisTemplate.boundHashOps("UserCF").put(uid.toString(),s);
            System.out.println();
        }
    }
}
